#include "glwidget.h"
#include <QPainter>
#include <QPaintEngine>

GLfloat vertices[] = {
	-0.5, 0.5, 0.5, 0.5,-0.5,0.5,-0.5,-0.5,0.5,
	0.5, -0.5, 0.5, -0.5,0.5,0.5,0.5,0.5,0.5,
	-0.5, -0.5, -0.5, 0.5,-0.5,-0.5,-0.5,0.5,-0.5,
	0.5, 0.5, -0.5, -0.5,0.5,-0.5,0.5,-0.5,-0.5,

	0.5, -0.5, -0.5, 0.5,-0.5,0.5,0.5,0.5,-0.5,
	0.5, 0.5, 0.5, 0.5,0.5,-0.5,0.5,-0.5,0.5,
	-0.5, 0.5, -0.5, -0.5,-0.5,0.5,-0.5,-0.5,-0.5,
	-0.5, -0.5, 0.5, -0.5,0.5,-0.5,-0.5,0.5,0.5,

	0.5, 0.5,  -0.5, -0.5, 0.5,  0.5,  -0.5,  0.5,  -0.5,
	-0.5,  0.5,  0.5,  0.5,  0.5,  -0.5, 0.5, 0.5,  0.5,
	-0.5,  -0.5, -0.5, -0.5, -0.5, 0.5,  0.5, -0.5, -0.5,
	0.5, -0.5, 0.5,  0.5,  -0.5, -0.5, -0.5,  -0.5, 0.5
};

GLfloat texCoord[] = {
	0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
	1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,
	1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
	0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,

	1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
	0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,
	0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
	1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,

	0.0f,1.0f, 1.0f,0.0f, 1.0f,1.0f,
	1.0f,0.0f, 0.0f,1.0f, 0.0f,0.0f,
	1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f,
	0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f
};

GLfloat normals[] = {
	0,0,-1, 0,0,-1, 0,0,-1,
	0,0,-1, 0,0,-1, 0,0,-1,
	0,0,1, 0,0,1, 0,0,1,
	0,0,1, 0,0,1, 0,0,1,

	-1,0,0, -1,0,0, -1,0,0,
	-1,0,0, -1,0,0, -1,0,0,
	1,0,0, 1,0,0, 1,0,0,
	1,0,0, 1,0,0, 1,0,0,

	0,-1,0, 0,-1,0, 0,-1,0,
	0,-1,0, 0,-1,0, 0,-1,0,
	0,1,0, 0,1,0, 0,1,0,
	0,1,0, 0,1,0, 0,1,0
};


GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) {
	setAttribute(Qt::WA_PaintOnScreen);
	setAttribute(Qt::WA_NoSystemBackground);
	setAutoBufferSwap(false);
	#ifndef Q_WS_QWS
		setMinimumSize(300, 250);
	#endif
}

GLWidget::~GLWidget() {
}

void GLWidget::initializeGL() {
	render_fbo = new QGLFramebufferObject(512, 512);
	texture_fbo = new QGLFramebufferObject(512, 512);

	QGLShader *vshader = new QGLShader(QGLShader::Vertex);
	vshader->compileSourceFile("vertex.shader");
	QGLShader *fshader = new QGLShader(QGLShader::Fragment);
	fshader->compileSourceFile("fragment.shader");
	program.addShader(vshader);
	program.addShader(fshader);
	program.link();

	vertexAttr = program.attributeLocation("vertex");
	normalAttr = program.attributeLocation("normal");
	texCoordAttr = program.attributeLocation("texCoord");
	matrixUniform = program.uniformLocation("matrix");
	textureUniform = program.uniformLocation("tex");

	m_fAngle = 0;
	m_fScale = 0.5;
}

void GLWidget::paintGL() {
	QPainter fbo_painter(render_fbo);
	QColor penColor = QColor(255,255,255);
	QPen pen = QPen(penColor);
	pen.setWidth(5);
	fbo_painter.setPen(pen);
	fbo_painter.drawEllipse(50,50,50,50);
	fbo_painter.end();

	if (render_fbo != texture_fbo) {
		QRect render_rect(0, 0, render_fbo->width(), render_fbo->height());
		QRect texture_rect(0, 0, texture_fbo->width(), texture_fbo->height());
		QGLFramebufferObject::blitFramebuffer(texture_fbo, texture_rect, render_fbo, render_rect);
	}

	fbo_painter.begin(this);
	fbo_painter.beginNativePainting();
		glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

		glFrontFace(GL_CW);
		glCullFace(GL_FRONT);
		glEnable(GL_CULL_FACE);
		glEnable(GL_DEPTH_TEST);

		QMatrix4x4 modelview;
		modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f);
		modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f);
		modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f);
		modelview.scale(m_fScale);
		modelview.translate(0.0f, -0.2f, 0.0f);

		program.bind();
		program.setUniformValue(matrixUniform, modelview);

		glBindTexture(GL_TEXTURE_2D, texture_fbo->texture());

		program.setAttributeArray(vertexAttr, vertices, 3);
		program.setAttributeArray(texCoordAttr, texCoord, 2);
		program.setAttributeArray(normalAttr, normals, 3);

		program.setUniformValue(textureUniform, 0);    // use texture unit 0

		program.enableAttributeArray(vertexAttr);
		program.enableAttributeArray(normalAttr);
		program.enableAttributeArray(texCoordAttr);

		glDrawArrays(GL_TRIANGLES, 0, 36);

		program.disableAttributeArray(vertexAttr);
		program.disableAttributeArray(normalAttr);
		program.disableAttributeArray(texCoordAttr);

		program.release();

		glDisable(GL_DEPTH_TEST);
		glDisable(GL_CULL_FACE);
	fbo_painter.endNativePainting();

	m_fAngle += 1.0f;
	swapBuffers();
}
